import org.apache.commons.lang.WordUtils;

import grails.util.GrailsNameUtils;
import groovy.text.GStringTemplateEngine

includeTargets << grailsScript("_GrailsBootstrap")
includeTargets << grailsScript("_GrailsCreateArtifacts")

target (generateMarionetteViews: "Generates the CRUD marionette views for a specified domain class") {

	depends(checkVersion, parseArguments, packageApp, loadApp)
	
	promptForName(type: "Domain Class")

	String name = argsMap['params'][0]
	
	println "Generating Marionette JS views for ${name}"
	
	if (name && name!='*') {
		name = name.indexOf('.') > 0 ? name : GrailsNameUtils.getClassNameRepresentation(name)
		def domainClass = grailsApp.getDomainClass(name)
	
		if (!domainClass) {
			println "No Domain Class named ${name} found!"
			return
		}
		
		def domainShortName = WordUtils.uncapitalize(domainClass.getShortName())
		def appName = grails.util.Metadata.current.'app.name'
		
		//prepare output folder structure
		def (outputDirPath, libDir, appDir, viewsDir, collectionsDir, modelsDir, gpsDir, gspTemplatesDir) = createFolderStructure(domainShortName)
		
		def templateDirPath = "${puppeteerPluginDir}/src/templates/marionette"

		def domainBinding = [domainClass:domainShortName, capDomainClass: domainClass.getShortName(), appName:appName]
		
		//underscore base copy, needed for getting along with Grails, via {{}}-Templates 
		copyLibs(templateDirPath,libDir)
	
		//generate main working js files
		def mainJs = generateClassIfNotExists("${templateDirPath}/Main.groovy", domainBinding, "${appDir.getAbsolutePath()}/main.js")
		
		def ventJs = generateClassIfNotExists("${templateDirPath}/Vent.groovy", domainBinding, "${appDir.getAbsolutePath()}/vent.js")
		
		def appJs = generateClassIfNotExists("${templateDirPath}/App.groovy", domainBinding, "${appDir.getAbsolutePath()}/app.js")
		
		//generate views
		def messageViewJs = generateClassIfNotExists("${templateDirPath}/views/MessageView.groovy", domainBinding, "${viewsDir.getAbsolutePath()}/messageView.js")
		def domainCollectionViewJs = generateClassIfNotExists("${templateDirPath}/views/DomainCollectionView.groovy", domainBinding, "${viewsDir.getAbsolutePath()}/${domainShortName}CollectionView.js")
		def domainDetailsViewJs = generateClassIfNotExists("${templateDirPath}/views/DomainDetailsView.groovy", domainBinding, "${viewsDir.getAbsolutePath()}/${domainShortName}DetailsView.js")
		def domainModelViewJs = generateClassIfNotExists("${templateDirPath}/views/DomainModelView.groovy", domainBinding, "${viewsDir.getAbsolutePath()}/${domainShortName}ModelView.js")
		def domainTableViewJs = generateClassIfNotExists("${templateDirPath}/views/DomainTableView.groovy", domainBinding, "${viewsDir.getAbsolutePath()}/${domainShortName}TableView.js")
		
		//generate model
		def domainModelJs = generateClassIfNotExists("${templateDirPath}/models/DomainModel.groovy", domainBinding, "${modelsDir.getAbsolutePath()}/${domainShortName}Model.js")
		def domainCollectionJs = generateClassIfNotExists("${templateDirPath}/models/DomainCollection.groovy", domainBinding, "${collectionsDir.getAbsolutePath()}/${domainShortName}Collection.js")
		
		//generate gsp and templates
		def indexGsp = generateClassIfNotExists("${templateDirPath}/views/gsp/index.gsp", domainBinding, "${gpsDir.getAbsolutePath()}/${domainShortName}App.gsp")
		def tableTemplateGsp = generateClassIfNotExists("${templateDirPath}/views/gsp/_table_panel.gsp", domainBinding, "${gspTemplatesDir.getAbsolutePath()}/_table_panel.gsp")
		def tableRowTemplateGsp = generateClassIfNotExists("${templateDirPath}/views/gsp/_table_panel_row.gsp", domainBinding, "${gspTemplatesDir.getAbsolutePath()}/_table_panel_row.gsp")
		def messageTemplateGsp = generateClassIfNotExists("${templateDirPath}/views/gsp/_message.gsp", domainBinding, "${gspTemplatesDir.getAbsolutePath()}/_message.gsp")
		def detailsTemplateGsp = generateClassIfNotExists("${templateDirPath}/views/gsp/_table_details_form.gsp", domainBinding, "${gspTemplatesDir.getAbsolutePath()}/_table_details_form.gsp")
		
		
	}
}

def createFolderStructure(domainShortName){
	def outputDirPath = "${basedir}/web-app/js"
	
	def libDirPath = "${outputDirPath}/lib"
	
	def appDirPath = "${outputDirPath}/${domainShortName}"
	def viewsDirPath = "${appDirPath}/views"
	def collectionsDirPath = "${appDirPath}/collections"
	def modelsDirPath = "${appDirPath}/models"
	
	def gspPath = "${basedir}/grails-app/views/${domainShortName}"
	def gspTemplatesPath = "${basedir}/grails-app/views/${domainShortName}/templates"
	
	//prepare folder structure
	def libDir = generateFolderIfNotExists(libDirPath)
	
	def appDir = generateFolderIfNotExists(appDirPath)
	def viewsDir = generateFolderIfNotExists(viewsDirPath)
	def collectionsDir = generateFolderIfNotExists(collectionsDirPath)
	def modelsDir = generateFolderIfNotExists(modelsDirPath)
	
	def gspDir = generateFolderIfNotExists(gspPath)
	def gspTemplatesDir = generateFolderIfNotExists(gspTemplatesPath)
	
	return [outputDirPath, libDir, appDir, viewsDir, collectionsDir, modelsDir, gspDir, gspTemplatesDir]
}

File generateFolderIfNotExists(path){
	
	def dir = new File(path)
	if(!dir.exists()){
		dir.mkdirs()
	}
	
	return dir
}

def File generateClassIfNotExists(templatePath, domainBinding, outputPath){
	
	def templateFile = new File(templatePath)
	
	if(!templateFile.exists()){
		println "ERROR! Missing Template: $templatePath"
		return	
	}
	
	def engine = new GStringTemplateEngine()
		
	//generating this template
	def template = engine.createTemplate(templateFile).make(domainBinding)
		
	def outputFile = new File(outputPath)
		
	if(!outputFile.exists()){
			
		println "Generating: "+outputFile.toString()
			
		outputFile.createNewFile()
			outputFile << template	
			
	}else{
		
		println "$outputPath already exists! ignoring generation for this file.."
	}		
}


def copyLibs(String templatePath, File libDir){
	
	def underScoreBaseTemplate = new File("$templatePath/underscore-base.js")
	
	if(!underScoreBaseTemplate.exists()){
		println "ERROR! Underscore base template missing.."	
		return
	}
	
	def underScoreOutput = new File(libDir.getAbsolutePath()+"/underscore-base.js")
	
	if(underScoreOutput.exists()){
		println "Undescore base lib already exists. Ignoring generation for this file.."
		return
	}
	
	underScoreOutput.createNewFile()
	
	underScoreOutput << underScoreBaseTemplate.text
}

USAGE = """
    generate-marionette-views [NAME]

where
    NAME       = Either a domain class name (case-sensitive). 
				 If you specify the wildcard then
				 views will be generated for all domain classes.
"""

setDefaultTarget 'generateMarionetteViews'